#!/usr/bin/env bash

requirements_find_smf()
{
  if # find SMF in PATH
    __rvm_which sm >/dev/null 2>&1
  then
    return 0
  else # find SMF out of PATH and link to rvm/bin
    \typeset __binary
    for __binary in ~/.sm/bin/sm /opt/sm/bin/sm
    do
      if
        [[ -f "${__binary}" && -s "${__binary}" && -x "${__binary}" ]]
      then
        PATH="$PATH:${__binary%/*}"
        return 0
      fi
    done
    return 1
  fi
}

__smf_try_sudo()
{
  if [[ -w "$( __rvm_which sm )" ]]
  then "$@"
  else __rvm_try_sudo "$@"
  fi
}

requirements_smf_lib_installed()
{
  sm pkg list | __rvm_grep "^${1}:" >/dev/null || return $?
}

requirements_smf_lib_install_command()
{
  __smf_install_command=( sm "$1" install )
  if
    [[ "${rvm_static_flag:-}" == "1" ]]
  then
    __smf_install_command=(
      /usr/bin/env CFLAGS="-fPIC" LDFLAGS="-fPIC" "${__smf_install_command[@]}" static
    )
  fi
  __smf_install_command=( __smf_try_sudo "${__smf_install_command[@]}" )
}

requirements_smf_lib_install()
{
  \typeset -a __smf_install_command
  requirements_smf_lib_install_command "$@"
  rvm_debug "__smf_install_command: ${__smf_install_command[*]};"
  "${__smf_install_command[@]}" ||
  {
    \typeset ret=$?
    rvm_warn "There were package installation errors with SM Framework, make sure to read the log.
If you see this on OSX, then you might want to try macports (https://www.macports.org/) or homebrew (http://brew.sh/) and tell RVM to use them by running:

    rvm autolibs macports #OR
    rvm autolibs homebrew

You might get help by reporting tickets to https://github.com/sm/sm/issues"
    return $ret
  }
  shift
}

requirements_smf_gcc_42_check()
{
  case "$1" in
    (ruby-2*|ruby-head) true ;; # ruby-2.0.0+ is supposed to work with clang
    (*)
      # install gcc-4.2 only if not yet available, prevents problems with gcc-4.2 on OSX 10.6
      if
        ! __rvm_which gcc-4.2 >/dev/null &&
        __rvm_compiler_is_llvm
      then
        rvm_error "SM Framework does not know how to install gcc-4.2, please install osx-gcc-installer first for older rubies."
      fi
      ;;
  esac
}

requirements_smf_install_extension_sets()
{
  \typeset __set
  for __set
  do __smf_try_sudo sm set install "${__set}" || return $?
  done
}

requirements_smf_update_system_ensure_etc_openssl()
{
  [[ -d "/etc/openssl" ]] || __rvm_try_sudo mkdir -p "/etc/openssl" || return $?
  [[ -w "/etc/openssl" ]] ||
  {
    __rvm_try_sudo chmod -R 755   "/etc/openssl" &&
    __rvm_try_sudo chown -R $USER "/etc/openssl"
  } || return $?
}

requirements_smf_update_system()
{
  requirements_smf_update_system_ensure_etc_openssl || return $?
  __rvm_log_command sm_get_head "Updating SMF" __smf_try_sudo sm get head || return $?
  if
    [[ "${#required_extension_sets[@]}" -gt 0 ]]
  then
    __rvm_log_command sm_install_extension_sets "Installing/updating extension sets: ${required_extension_sets[*]}" \
      requirements_smf_install_extension_sets "${required_extension_sets[@]}" ||
      return $?
  fi
}

requirements_smf_define_git()
{
  __rvm_which git >/dev/null || {
    required_extension_sets+=( vcs )
    requirements_check autoconf git || return $?
  }
}

requirements_smf_define()
{
  case "$1" in
    (rvm)
      true
      ;;

    (jruby*)
      requirements_check make

      if
        is_head_or_disable_binary "$1"
      then
        requirements_smf_define_git || return $?
        case $( jruby_installation_method  "$1" ) in
          ant) __rvm_which ant >/dev/null 2>&1 || return $? ;;
          mvn) requirements_check_custom_after mvn=maven    ;;
        esac
      fi
      __rvm_which java >/dev/null 2>&1 || return $?
      ;;

    (ir*)
      __rvm_which mono >/dev/null 2>&1 || return $?
      ;;

    (opal)
      required_extension_sets+=( javascript )
      requirements_check node
      ;;

    (*-head)
      requirements_smf_define default
      requirements_smf_define_git || return $?
      ;;

    (*)
      required_extension_sets+=( databases gnu libraries tools )
      if
        [[ "${_system_name}" == "OSX" ]]
      then
        # TODO: ruby up to 1.9.3 requires openssl 0.9.8 on OSX
        if __rvm_version_compare "${_system_version}" -ge 10.9
        then requirements_check pkg-config libyaml zlib ncurses readline openssl sqlite3 gdbm
        else requirements_check pkg-config libtool libyaml zlib ncurses readline openssl sqlite3 gdbm
        fi
      else
        requirements_check pkg-config libtool libyaml zlib ncurses ncursesw readline openssl sqlite3 gdbm
      fi
      ;;
  esac
}

requirements_smf_install_sm()
{
  rvm_error "SMF Framework support is only intended for RailsInstaller / Tokaido.app, please use Macports / Homebrew integration instead."
  return 100
}

requirements_smf_ensure_smf_available()
{
  __rvm_which sm >/dev/null ||
  {
    rvm_requiremnts_fail_or_run_action 2 \
      "Requested installation with SM Framework, but SM Framework is not available." \
      requirements_smf_install_sm ||
      return $?
  }
}

requirements_smf_find_sm()
{
  export __sm_path
  : __sm_path:${__sm_path:=$( __rvm_which sm )}
  __rvm_readlink_deep __sm_path
  [[ -n "${__sm_path}" ]] || return $?
}

requirements_smf_before()
{
  required_extension_sets=()
  requirements_smf_ensure_smf_available || return $?
  requirements_smf_find_sm              || return $?
}

requirements_smf_after()
{
  requirements_smf_gcc_42_check "$1" || return $?

  if
    [[ "${_system_name}" == "OSX" ]]
  then
    case "$1" in
      (ruby-1*|ruby-2.0*)
        __rvm_update_configure_env LDFLAGS="-Z -L${__sm_path%/bin/sm}/pkg/active/lib -L/usr/lib"
        ;;
      (*) # 2.1.0+
        __rvm_update_configure_env LDFLAGS="-L${__sm_path%/bin/sm}/pkg/active/lib"
        ;;
    esac
    __rvm_update_configure_env CFLAGS="-I${__sm_path%/bin/sm}/pkg/active/include"
  fi

  case "$PATH" in
   (${__sm_path%/bin/sm}/pkg/active/bin:*)
     true
     ;;
   (*)
     __rvm_add_to_path prepend "${__sm_path%/bin/sm}/pkg/active/bin"
     ;;
  esac

  export PKG_CONFIG_PATH="${__sm_path%/bin/sm}/pkg/active/lib/pkgconfig"

  case "$1" in
    (jruby*) true ;;
    (*) requirements_smf_after_update_certs_openssl ;;
  esac
}

requirements_smf_after_update_certs_openssl()
{
  requirements_osx_update_openssl_cert "${__sm_path%/bin/sm}/pkg/active/bin/openssl" || return $?
}
